use rubato::{FftFixedIn, FftFixedOut, Resampler, SincFixedOut};
use std::path::Path;
use symphonia::core::audio::{AudioBufferRef, Signal};
use symphonia::core::codecs::{CODEC_TYPE_NULL, DecoderOptions};
use symphonia::core::formats::FormatOptions;
use symphonia::core::io::{MediaSource, MediaSourceStream, MediaSourceStreamOptions};
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use tokio::sync::mpsc::Sender;

pub(crate) async fn read_sound_file(
    path: &'static str,
    sample_rate: u32,
    tx: Sender<Vec<f32>>,
) -> Result<(), anyhow::Error> {
    let path = Path::new(path);
    let exten_str = path.extension().and_then(|s| s.to_str()).unwrap_or("");
    let files = std::fs::File::open(path)?;
    files.byte_len();

    let mss = MediaSourceStream::new(Box::new(files), MediaSourceStreamOptions::default());

    // 根据 file 的扩展名，设置
    let mut hint = Hint::new();
    hint.with_extension(exten_str);

    // 获取默认的 Meta 和 format
    let meta_opts: MetadataOptions = MetadataOptions::default();
    let fmt_opts: FormatOptions = FormatOptions::default();

    // 探针
    let probed = symphonia::default::get_probe().format(&hint, mss, &fmt_opts, &meta_opts)?;
    // 获取到一个格式读取器
    let mut format = probed.format;

    // 获取第一个音频轨道, 取的是非空第一个
    let track = format
        .tracks()
        .iter()
        .find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
        .expect("");

    let codec_p = &track.codec_params;
    let mut sample_r = 0;
    let n_frames = codec_p.n_frames.unwrap_or(0);
    let total_time = if let Some(sample_rate) = codec_p.sample_rate {
        sample_r = sample_rate;
        n_frames * 1000 / sample_rate as u64
    } else {
        0
    };
    let channels = codec_p.channels.unwrap_or_default().count();
    tx.send(vec![total_time as f32, sample_r as f32, channels as f32])
        .await
        .unwrap_or_default();

    println!("channels: {}, sample_rate: {},  codec_p: {:?}", channels, sample_rate, codec_p);
    // 解码器的默认选项
    let dec_opts: DecoderOptions = DecoderOptions::default();

    // 获取到一个解码器
    let mut decoder = symphonia::default::get_codecs().make(&track.codec_params, &dec_opts)?;

    // 存储磁道标识符，用于过滤数据包
    let track_id = track.id;
    // let chunk_size_out: usize = c * 44100 / 48000;
    // println!("chunk_size_out: {}", chunk_size_out);
    // let mut sfft: FftFixedOut<f32> = FftFixedOut::new(44100, 48000, chunk_size_out, 2, 1)?;
    let mut chunk_size:usize = 1152;
    let mut sfft: Option<FftFixedIn<f32>> = if sample_rate != sample_r {
        Some(FftFixedIn::new(sample_r as usize, sample_rate as usize, chunk_size, 2, 1)?)
    } else {
        None
    };
    
    // 循环解码
    loop {
        // 从媒体格式获取下一个数据包。
        let packet = match format.next_packet() {
            Ok(p) => p,
            Err(symphonia::core::errors::Error::ResetRequired) => {
                unimplemented!()
            }
            Err(symphonia::core::errors::Error::IoError(err))
                if err.kind() == std::io::ErrorKind::UnexpectedEof =>
            {
                continue;
            }
            Err(symphonia::core::errors::Error::IoError(err)) => {
                println!("packet error: {:?}", err);
                return Err(anyhow::Error::msg(format!("{:?}", err)));
            }
            Err(err) => {
                println!("packet error: {:?}", err);
                return Err(anyhow::Error::msg(format!("{:?}", err)));
            }
        };

        // 使用自上一个数据包以来读取的任何新元数据。
        while !format.metadata().is_latest() {
            // 弹出 元数据
            let data = format.metadata().pop();
            // 使用这个数据
            if let Some(metadata) = data {
                println!("metadata: {:?}", metadata);
            }
        }

        // 如果数据不属于选中的数据，弹出
        if packet.track_id() != track_id {
            continue;
        }

        match decoder.decode(&packet) {
            Ok(buffer) => {
                // 使用解码后的音频样本
                match buffer {
                    AudioBufferRef::F32(buf) => {
                        // channel 数量
                        let datas = buf.chan(0);
                        let datas_len = datas.len();
                         if let Some(sfft) = &mut sfft {
                            if chunk_size != datas_len {
                                chunk_size = datas_len;
                                sfft.set_chunk_size(chunk_size);
                            }
                            let out_datas = &(sfft.process(&[datas], None)?[0]);
                       
                            if channels == 2 {
                                let d = out_datas.iter().flat_map(|&s| [s, s]).collect();
                                tx.send(d).await?;
                            } else {
                                tx.send(out_datas.to_vec()).await?;
                            }
                            // out_datas
                        } else {
                            if channels == 2 {
                                let d = datas.iter().flat_map(|&s| [s, s]).collect();
                                tx.send(d).await?;
                            } else {
                                tx.send(datas.to_vec()).await?;
                            }
                        }
                    }
                    AudioBufferRef::S16(buf) => {
                        let datas = buf.chan(0);
                        let c_data:Vec<f32> =  datas.iter()
                            .flat_map(|&s| {
                                let f32_sample = (s as f32 /32768.0);
                                if channels == 2 {
                                    vec![f32_sample , f32_sample]
                                }else {
                                    vec![f32_sample]
                                }
                            })
                            .collect();
                        let datas_len = c_data.len();
                        println!("c_data:len: {}", c_data.len());
                        if sample_rate != sample_r {
                            if chunk_size != datas_len {
                                chunk_size = datas_len;
                                sfft  = Some(FftFixedIn::new(sample_r as usize, sample_rate as usize, chunk_size, 2, 1)?);
                            }
                            if let Some(sfft2) = &mut sfft {
                                let out_datas = &(sfft2.process(&[c_data], None)?[0]);
                                tx.send(out_datas.to_vec()).await?;

                            } else {
                                tx.send(c_data.to_vec()).await?;
                            }
                        }else {
                            tx.send(c_data.to_vec()).await?;
                        }
                        
                    }
                    AudioBufferRef::U16(buf) => {
                        let datas = buf.chan(0);
                        let c_data:Vec<f32> =  datas.iter()
                            .flat_map(|&s| {
                                let f32_sample = (s as f32 / 32767.5) - 1.0;
                                if channels == 2 {
                                    vec![f32_sample , f32_sample]
                                }else {
                                    vec![f32_sample]
                                }
                            })
                            .collect();
                        let datas_len = c_data.len();
                        println!("c_data:len: {}", c_data.len());
                        if let Some(sfft) = &mut sfft {
                            if chunk_size != datas_len {
                                chunk_size = datas_len;
                                sfft.set_chunk_size(chunk_size).unwrap_or_default();
                            }
                            let out_datas = &(sfft.process(&[c_data], None)?[0]);
                            tx.send(out_datas.to_vec()).await?;

                        } else {
                            tx.send(c_data.to_vec()).await?;
                        }
                    }
                    AudioBufferRef::U8(buf) => {
                        // channel 数量
                        let datas = buf.chan(0);
                        let c_data:Vec<f32> =  datas.iter()
                            .flat_map(|&s| {
                                let f32_sample = (s as f32 - 128.0) / 128.0;
                                if channels == 2 {
                                    vec![f32_sample , f32_sample]
                                }else {
                                    vec![f32_sample]
                                }
                            })
                            .collect();
                        let datas_len = c_data.len();
                        println!("c_data:len: {}", c_data.len());
                        if let Some(sfft) = &mut sfft {
                            if chunk_size != datas_len {
                                chunk_size = datas_len;
                                sfft.set_chunk_size(chunk_size).unwrap_or_default();
                            }
                            let out_datas = &(sfft.process(&[c_data], None)?[0]);
                            tx.send(out_datas.to_vec()).await?;

                        } else {
                            tx.send(c_data.to_vec()).await?;
                        }
                    }
                    AudioBufferRef::U24(buf) => {
                        println!("AudioBufferRef::U24");
                    }
                    AudioBufferRef::U32(buf) => {
                        println!("AudioBufferRef::U32");
                    }
                    AudioBufferRef::S24(buf) => {
                        println!("AudioBufferRef::S24");
                    }
                    AudioBufferRef::F64(buf) => {
                        println!("AudioBufferRef::F64");
                    }
                    _ => {
                        unimplemented!()
                    }
                }
            }
            Err(symphonia::core::errors::Error::IoError(_)) => {
                // 由于IO错误，数据包解码失败，请跳过该数据包。
                continue;
            }
            Err(symphonia::core::errors::Error::DecodeError(_)) => {
                // 由于数据无效，数据包解码失败，跳过数据包。
                continue;
            }
            Err(err) => {
                return Err(anyhow::Error::msg(format!("{:?}", err)));
            }
        }
    }

    Ok(())
}
